const http = require('http')
const os = require('os')
const path = require('path')
const chalk = require('chalk')
const url = require('url')
const fs = require('fs')
const mime = require('mime')
const template = require('art-template')
const { isDirectory } = require('./util')

const address = Object.values(os.networkInterfaces())
  .flat()
  .find((item) => item.family === 'IPv4').address

class Server {
  constructor(options = {}) {
    this.port = options.port
    this.directory = options.directory
    this.handleRequest = this.handleRequest.bind(this)
  }

  handleRequest(req, res) {
    const pathname = url.parse(req.url).pathname
    const realPath = path.join(process.cwd(), pathname)
    console.log('realPath', realPath)
    console.log('pathname', pathname)
    fs.stat(realPath, (err, info) => {
      if (err) {
        console.log(`${realPath} 有问题`)
        // console.log(err)
        return
      }
      if (info.isDirectory()) {
        this.sendDir(res, realPath, pathname)
      } else {
        this.sendFile(res, realPath)
      }
    })
  }

  sendDir(res, realPath, pathname) {
    fs.readdir(realPath, async (err, list) => {
      const fullPathList = list.map((p) => path.resolve(realPath, p))
      const fullObj = []
      for (let i = 0; i < fullPathList.length; ++i) {
        let obj = {
          name: list[i],
          path: fullPathList[i],
          clientPath:
            pathname === '/' ? pathname + list[i] : pathname + '/' + list[i]
        }
        obj.isDirectory = await isDirectory(obj.path)
        fullObj.push(obj)
      }
      const str = template(path.resolve(__dirname, '../public/index.html'), {
        arr: fullObj
      })
      res.end(str)
    })
  }

  sendFile(res, realPath) {
    const type = mime.getType(realPath)
    res.setHeader('Content-Type', `${type} ;chartset=utf-8`)
    const arr = []
    const readStream = fs.createReadStream(realPath, { highWaterMark: 4 })
    readStream.on('open', () => {})
    readStream.on('data', (chunk) => {
      arr.push(chunk)
    })
    readStream.on('end', () => {
      res.end(Buffer.concat(arr))
    })
  }

  start() {
    const s = http.createServer(this.handleRequest)
    s.listen(this.port, (err) => {
      console.log(
        `${chalk.yellow(
          'Starting up simple-server, serving:'
        )} ./${path.relative(process.cwd(), this.directory)}`
      )
      console.log(`正在监听 http://localhost:${chalk.green(this.port)}`)
      console.log(`正在监听 http://${address}:${chalk.green(this.port)}`)
    })
  }
}

module.exports = Server
